﻿using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace ElevatorDispatching
{

    /// <summary>
    ///     <see cref="INotifyPropertyChanged" /> 接口的基本实现，用以简化模型。
    /// </summary>
    public abstract class BindableBase : INotifyPropertyChanged
    {
        protected object SyncRoot { get; } = new object();

        /// <summary>
        ///     在属性值更改时发生
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        ///     通知监听器，属性的值发生了改变。
        /// </summary>
        /// <param name="propertyName">发生改变的属性的名称。该值可选，它可以由编译器基于 <see cref="CallerMemberNameAttribute"/> 属性自动提供。</param>
        ///     Name of the property used to notify listeners.  This
        ///     value is optional and can be provided automatically when invoked from compilers
        ///     that support <see cref="CallerMemberNameAttribute" />.
        /// </param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        /// <summary>
        ///     检查一个属性的目标值是否与原始值不相等，在不相等时设置属性值并像监听器发出通知。
        /// </summary>
        /// <typeparam name="T">属性的类型</typeparam>
        /// <param name="storage">对存储属性值的字段的引用</param>
        /// <param name="value">属性的值</param>
        /// <param name="propertyName">用于属性变化通知的属性名。该值可选，它可以由编译器基于 <see cref="CallerMemberNameAttribute"/> 属性自动提供。</param>
        /// <returns>当属性值被改变时返回 true，否则（目标值与原始值一致）则返回 false。</returns>
        protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value)) return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }
}
